﻿using System;
using System.Net;
using System.Xml.Serialization;

namespace Cnblogs.Service
{
    public enum ServiceType
    {
        /// <summary>
        /// 首页
        /// </summary>
        Home,
        /// <summary>
        /// 热门新闻
        /// </summary>
        Hot,
        /// <summary>
        /// 最新新闻
        /// </summary>
        Recent,
        /// <summary>
        /// 推荐新闻
        /// </summary>
        Recommend,
        /// <summary>
        /// 新闻评论
        /// </summary>
        NewsComment,
        /// <summary>
        /// 博客正文的评论
        /// </summary>
        PostComment,
        /// <summary>
        /// 新闻的正文
        /// </summary>
        Content,
        /// <summary>
        /// 搜索博主
        /// </summary>
        Search,
        /// <summary>
        /// 文章详细内容
        /// </summary>
        PostContent,
        /// <summary>
        /// 博主页面的文章
        /// </summary>
        Blogger,
    }

    public class NewsData
    {
        /// <summary>
        /// 新闻的id
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// 每页的新闻个数
        /// </summary>
        public int PageSize { get; set; }

        /// <summary>
        /// 当前的页码
        /// </summary>
        public int PageIndex { get; set; }

        /// <summary>
        /// 搜索的关键字
        /// </summary>
        public string Key { get; set; }

        public NewsData()
        {
            PageSize = 20;
            PageIndex = 1;
        }

        public NewsData(int page, int size)
        {
            this.PageIndex = page;
            this.PageSize = size;
        }
    }

    /// <summary>
    /// 数据服务类
    /// http://wcf.open.cnblogs.com/news/help
    /// http://wcf.open.cnblogs.com/blog/help
    /// </summary>
    public class FeedService
    {
        internal static string GetRequestUrl(ServiceType type, NewsData data)
        {
            string url = "";

            switch (type)
            {
                case ServiceType.Hot:
                    url = string.Format("http://wcf.open.cnblogs.com/news/hot/{0}", data.PageSize);
                    break;
                case ServiceType.Recent:
                    url = string.Format("http://wcf.open.cnblogs.com/news/recent/paged/{0}/{1}", data.PageIndex, data.PageSize);
                    break;
                case ServiceType.Recommend:
                    url = string.Format("http://wcf.open.cnblogs.com/news/recommend/paged/{0}/{1}", data.PageIndex, data.PageSize);
                    break;
                case ServiceType.PostComment:
                    url = string.Format("http://wcf.open.cnblogs.com/blog/post/{0}/comments/{1}/{2}", data.Id, data.PageIndex, data.PageSize);
                    break;
                case ServiceType.NewsComment:
                    url = string.Format("http://wcf.open.cnblogs.com/news/item/{0}/comments/{1}/{2}", data.Id, data.PageIndex, data.PageSize);
                    break;
                case ServiceType.Content:
                    url = string.Format("http://wcf.open.cnblogs.com/news/item/{0}", data.Id);
                    break;
                case ServiceType.Search:
                    url = string.Format("http://wcf.open.cnblogs.com/blog/bloggers/search?t={0}", data.Key);
                    break;
                case ServiceType.Blogger:
                    url = string.Format("http://wcf.open.cnblogs.com/blog/u/{0}/posts/{1}/{2}", data.Key, data.PageIndex, data.PageSize);
                    break;
                case ServiceType.Home:
                    url = string.Format("http://wcf.open.cnblogs.com/blog/sitehome/paged/{0}/{1}", data.PageIndex, data.PageSize);
                    break;
                case ServiceType.PostContent:
                    url = string.Format("http://wcf.open.cnblogs.com/blog/post/body/{0}", data.Id);
                    break;
                default:
                    break;
            }
            return url;
        }

        internal static HttpWebRequest _httpWebRequest;
        public static void Request(ServiceType type, NewsData data, Action<object, bool> action)
        {
            _httpWebRequest = null;
            _httpWebRequest = (HttpWebRequest)WebRequest.Create(GetRequestUrl(type, data));
            _httpWebRequest.Method = "GET";
            _httpWebRequest.BeginGetResponse((result) => ResponseCallback(result, type, action), _httpWebRequest);
        }

        static object _obj = new object();
        internal static void ResponseCallback(IAsyncResult result, ServiceType type, Action<object, bool> action)
        {
            HttpWebRequest request = (HttpWebRequest)result.AsyncState;
            HttpWebResponse httpWebResponse;
            try
            {
                httpWebResponse = (HttpWebResponse)request.EndGetResponse(result);
            }
            catch (WebException we)
            {
                action(we, false);
                return;
            }
            if (httpWebResponse != null)
            {
                lock (_obj)
                {
                    using (var stream = httpWebResponse.GetResponseStream())
                    {
                        try
                        {
                            XmlSerializer ser = null;
                            object obj = null;
                            switch (type)
                            {
                                case ServiceType.Home:
                                case ServiceType.Hot:
                                case ServiceType.Recent:
                                case ServiceType.Recommend:
                                case ServiceType.PostComment:
                                case ServiceType.NewsComment:
                                    ser = new XmlSerializer(typeof(NewsFeed));
                                    break;
                                case ServiceType.Content:
                                    ser = new XmlSerializer(typeof(NewsBody));
                                    break;
                                case ServiceType.Search:
                                    ser = new XmlSerializer(typeof(SearchBloggerFeed));
                                    break;
                                case ServiceType.Blogger:
                                    ser = new XmlSerializer(typeof(BloggerFeed));
                                    break;
                                case ServiceType.PostContent:
                                    ser = new XmlSerializer(typeof(PostBody));
                                    break;
                                default:
                                    break;
                            }
                            obj = ser.Deserialize(stream);
                            action(obj, true);
                        }
                        catch (Exception se)
                        {
                            action(se, false);
                            return;
                        }
                    }
                }
            }
        }

    }
}
